#include "StdAfx.h"
#include "Sword.h"
#include "Actor.h"
#include "GameRules.h"
#include "ItemSharedParams.h"
#include "Player.h"
#include "CryMove.h"

CSword::CSword()
{
	lastTargetPosition=ZERO;
	collisionNorm=ZERO;
}


CSword::~CSword()
{
}

void CSword::PickUp(EntityId pickerId, bool sound, bool select, bool keepHistory, const char *setup)
{
	CActor *pActor=GetActor(pickerId);
	if (!pActor)
		return;
	if (pickerId==GetOwnerId())
		return;

	TriggerRespawn();

	GetEntity()->EnablePhysics(true);
	Physicalize(true, true);

	//bool soundEnabled = IsSoundEnabled();
	//EnableSound(sound);

	//SetViewMode(0);
	SetOwnerId(pickerId);

	//CopyRenderFlags(GetOwner());

	//Hide(true);
	//m_stats.dropped = false;
	//m_stats.brandnew = false;

	// move the entity to picker position
	Matrix34 tm(pActor->GetEntity()->GetWorldTM());
	tm.AddTranslation(Vec3(0,0,2));
	GetEntity()->SetWorldTM(tm);

	bool alone = true;
	bool slave = false;
	IInventory *pInventory = pActor->GetInventory();
	if (!pInventory)
	{
		GameWarning("Actor '%s' has no inventory, when trying to pickup '%s'!",pActor->GetEntity()->GetName(),GetEntity()->GetName());
		return;
	}

	OnPickedUp(pickerId, m_sharedparams->params.unique && !alone);	// some weapons will get ammo when picked up
																										// this will dictate the result of CanSelect() below
	EnableUpdate(true, eIUS_General);


	IPhysicalEntity* pPhysics = GetEntity()->GetPhysics();
	pe_params_articulated_body pab;
	pab.bGrounded = 0;
	pab.bCheckCollisions = 1;
	pab.bCollisionResp = 1;
	pPhysics->SetParams(&pab);

	//if (slave || alone || !m_sharedparams->params.unique)
	//{
	//	// add to inventory
		pInventory->AddItem(GetEntity()->GetId());
	//	SPlayerStats *pStats = NULL;
	//	if(pActor && pActor->GetActorClassType() == CPlayer::GetActorClassType())
	//		pStats = static_cast<SPlayerStats*>(pActor->GetActorStats());

	//	if (select && !pActor->GetLinkedVehicle() && !pActor->ShouldSwim() && (!pStats || !pStats->isOnLadder))
	//	{
	//		if(CanSelect() && !slave)
	//			m_pItemSystem->SetActorItem(pActor, GetEntity()->GetId(), keepHistory);
	//		else
	//			m_pItemSystem->SetActorAccessory(pActor, GetEntity()->GetId(), keepHistory);

	//		pActor->GetGameObject()->ChangedNetworkState(CPlayer::ASPECT_CURRENT_ITEM);
	//	}

	//	EnableSound(soundEnabled);

	//	if (IsServer() && g_pGame->GetGameRules())
	//		g_pGame->GetGameRules()->OnItemPickedUp(GetEntityId(), pickerId);

	//	PlayAction(g_pItemStrings->pickedup);
	//}

	//if (IsServer() && pActor)
	//{
	//	GetGameObject()->SetNetworkParent(pickerId);
	//	if ((GetEntity()->GetFlags()&(ENTITY_FLAG_CLIENT_ONLY|ENTITY_FLAG_SERVER_ONLY)) == 0)
	//	{
	//		pActor->GetGameObject()->InvokeRMIWithDependentObject(CActor::ClPickUp(), CActor::PickItemParams(GetEntityId(), m_stats.selected, sound), eRMI_ToAllClients|eRMI_NoLocalCalls, GetEntityId());

	//		const char *displayName=GetDisplayName();
	//	}
	//}
}

void CSword::Select(bool select)
{
	if(!m_ownerId)
		select = false;

	m_stats.selected=select;

	CheckViewChange();

	if (select)
	{
		Hide(false);
		EnableUpdate(true, eIUS_General);	
	}
	else
	{
		GetScheduler()->Reset(true);

		Hide(true);
		EnableUpdate(false);
	}

	OnSelected(select);
}

void CSword::Update( SEntityUpdateContext& ctx, int slot )
{
	UpdatePosition( ctx.fFrameTime );
}

void CSword::ProcessEvent( SEntityEvent& evt )
{
	CWeapon::ProcessEvent( evt );
	if (evt.event==ENTITY_EVENT_COLLISION)
	{
		EventPhysCollision *pCollision = (EventPhysCollision *)(evt.nParam[0]);

		if (pCollision->penetration>0.01f)
		{
			collisionNorm=pCollision->n;
		}
	}
}

void CSword::UpdatePosition( float dt )
{

	//get move values
	Vec3 movePosition = CryMove::GetInstance()->getConvertedPosition(0.1f);
	Quat moveRotation = CryMove::GetInstance()->getConvertedOrientation();
		
	movePosition.y+=2.0f;
	movePosition.z+=1.5f;

	//get player values
	IActor* pActor = gEnv->pGame->GetIGameFramework()->GetClientActor();
	Vec3 playerPosition = pActor->GetEntity()->GetPos();
	Quat playerRotation = pActor->GetEntity()->GetRotation();

	//compute target values
	Vec3 moveRelativePos = movePosition * !playerRotation;
	Vec3 targetPosition = playerPosition + moveRelativePos;
	Quat targetRotation = playerRotation * moveRotation;

	//get physics
	IPhysicalEntity* pPhysics = GetEntity()->GetPhysics();

	//get object dynamics
	pe_status_dynamics dyn;
	pPhysics->GetStatus( &dyn );

	if (lastTargetPosition==Vec3(0,0,0))
	{
		lastTargetPosition = targetPosition;
		lastTargetRotation = targetRotation;
	}
	Vec3 targetVel = (targetPosition - lastTargetPosition)/dt;
	Vec3 targetAngVel = (targetRotation * !lastTargetRotation).v/dt;
	lastTargetPosition = targetPosition;
	lastTargetRotation = targetRotation;

	//get object values
	Vec3 currentPosition = GetEntity()->GetPos();
	Quat currentRotation = GetEntity()->GetRotation();

	pe_action_set_velocity actionImp;
	actionImp.v = (targetPosition-currentPosition)*2.0f + targetVel;
	//handle collision
	float parallelPart  = actionImp.v.Dot(collisionNorm);
	if (parallelPart <0.0f)
	{
		actionImp.v-=collisionNorm*parallelPart ;
	}
	actionImp.w = (targetRotation*!currentRotation).v*5.0f + targetAngVel*2.0f;
	pPhysics->Action( &actionImp );
	collisionNorm=ZERO;
}